#pragma once

#include <QVector>
#include <QString>
#include <QHash>
#include <memory>

namespace application {

struct GraphNode {
    QString id;
    double x{0.0};
    double y{0.0};
    double direction{0.0};
    bool avoidWait{false}; // true if waiting on this node should be avoided (e.g., AP*, inter_point)
    QString blockAreaId;    // optional: block area (capacity 1) identifier

    GraphNode() = default;
    GraphNode(const QString& nodeId, double posX, double posY, double dir = 0.0, bool avoid = false, const QString& blockArea = QString())
        : id(nodeId), x(posX), y(posY), direction(dir), avoidWait(avoid), blockAreaId(blockArea) {}
};

struct GraphEdge {
    QString fromNodeId;
    QString toNodeId;
    double weight{0.0};
    QString pathType; // "bezier", "straight", "arc"

    GraphEdge() = default;
    GraphEdge(const QString& from, const QString& to, double w, const QString& type = "straight")
        : fromNodeId(from), toNodeId(to), weight(w), pathType(type) {}
};

class PathfindingGraph {
public:
    PathfindingGraph() = default;
    ~PathfindingGraph() = default;

    void addNode(const GraphNode& node);
    void addEdge(const GraphEdge& edge);

    const QVector<GraphNode>& getNodes() const { return nodes_; }
    const QVector<GraphEdge>& getEdges() const { return edges_; }

    // Mark an existing node as avoid-wait (no-op if not found)
    void markAvoidWait(const QString& nodeId, bool avoid = true);

    const GraphNode* findNode(const QString& nodeId) const;
    QVector<GraphEdge> getEdgesFromNode(const QString& nodeId) const;
    QVector<GraphEdge> getEdgesToNode(const QString& nodeId) const;

    bool hasNode(const QString& nodeId) const;
    bool hasEdge(const QString& fromId, const QString& toId) const;

    int getNodeCount() const { return nodes_.size(); }
    int getEdgeCount() const { return edges_.size(); }

    void clear();
    bool isEmpty() const { return nodes_.isEmpty(); }

private:
    QVector<GraphNode> nodes_;
    QVector<GraphEdge> edges_;
    QHash<QString, int> nodeIndexMap_;

    void rebuildIndexMap();
};

using PathfindingGraphPtr = std::shared_ptr<PathfindingGraph>;

} // namespace application
